package com.easylinkin.linkappapi.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.easylinkin.core.tree.TreeSelect;
import com.easylinkin.linkappapi.common.constant.CommonConstant;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappPrivilege;
import com.easylinkin.linkappapi.security.entity.LinkappRole;
import com.easylinkin.linkappapi.security.entity.LinkappRoleRefPrivilege;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.mapper.LinkappPrivilegeMapper;
import com.easylinkin.linkappapi.security.repository.LinkappPrivilegeRepository;
import com.easylinkin.linkappapi.security.service.LinkappPrivilegeService;
import com.easylinkin.linkappapi.security.service.LinkappRoleService;
import com.easylinkin.linkappapi.tenant.entity.TenantRefPrivilege;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import com.easylinkin.sm.constant.PrivilegeConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import site.morn.boot.data.CrudServiceSupport;
import site.morn.boot.jpa.SpecificationFunction;
import site.morn.core.CriteriaMap;
import site.morn.framework.context.AccountContext;
import site.morn.framework.entity.BasePrivilege.Fields;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限服务
 *
 * @author wujie
 * @since 0.1.1,  2019/08/28
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class LinkappPrivilegeServiceImpl extends
    CrudServiceSupport<LinkappPrivilege, Long, LinkappPrivilegeRepository> implements LinkappPrivilegeService {

  @Autowired
  LinkappRoleService roleService;

  @Autowired
  LinkappPrivilegeMapper privilegeMapper;
  @Autowired
  LinkappUserContextProducer linkappUserContextProducer;

  @Resource
  private CommonService commonService;

  @Resource
  private LinkappTenantMapper linkappTenantMapper;

  @Override
  public List<TreeSelect> searchPrivilegeTree(Integer disabled) {
//    List<TreeSelect> trees = new ArrayList();
//    // 根据当前用户的登录角色过滤
//    BaseLoginInfo baseLoginInfo = AccountContext.loginInfo();
//    List<LinkappPrivilege> privilegesList = (List<LinkappPrivilege>) baseLoginInfo.getPrivileges();
//    List<LinkappPrivilege> privileges = repository().findAllByParentId(0L);
//    if (!CollectionUtils.isEmpty(privileges)) {
//      privileges.forEach(privilege -> {
//        TreeSelect tree = this.privilegeToTreeSelect(privilege, disabled);
//        this.getTree(tree, privilegesList, disabled);
//        trees.add(tree);
//      });
//
//    }
    return null;
  }

  @Override
  public List<LinkappPrivilege> selectPrivilegeAll(LinkappPrivilege linkappPrivilege){
	  return privilegeMapper.selectPrivilegeAll(linkappPrivilege);
  }


  @Override
  public Collection<LinkappPrivilege> getCurrent() {
    // 获取当前用户
	  LinkappUser user = AccountContext.currentUser();
    Collection<LinkappRole> roles = roleService.getByUserId(user.getId());
    return roles.stream().flatMap(role -> role.getPrivileges().stream()).collect(Collectors.toList());
  }

  private void getTree(TreeSelect<LinkappPrivilege> treeNode, List<LinkappPrivilege> privilegesList, Integer disabled){
    List<LinkappPrivilege> filterList = privilegesList.stream().filter(privilege -> privilege.getParentId().equals(treeNode.getId())).collect(Collectors.toList());
    if (!filterList.isEmpty()) {
      List<TreeSelect<LinkappPrivilege>> children = new ArrayList();
      filterList.forEach(privilege -> {
        TreeSelect<LinkappPrivilege> currentTreeNode = this.privilegeToTreeSelect(privilege, disabled);
        children.add(currentTreeNode);
        this.getTree(currentTreeNode, privilegesList, disabled);
      });
      treeNode.setChildren(children);
    }
  }

  private TreeSelect<LinkappPrivilege> privilegeToTreeSelect(LinkappPrivilege privilege, Integer disabled){
    TreeSelect<LinkappPrivilege> treeSelect = new TreeSelect();
    treeSelect.setId(privilege.getId());
    treeSelect.setParentId(privilege.getParentId());
    treeSelect.setLabel(privilege.getName());
    treeSelect.setData(privilege);
    treeSelect.setIsDisabled(disabled != 0);
    return treeSelect;
  }

  @Override
  protected SpecificationFunction searchSpecificationFunction(LinkappPrivilege model, CriteriaMap attach) {
    return (reference, restrain, predicate) -> {
      model.setType(PrivilegeConstant.PRIVILEGE_TYPE_BUTTON);
      restrain.appendAnd(predicate.eq(Fields.parentId)).appendAnd(predicate.notEqual(Fields.type));
    };
  }

  @Override
  public List<LinkappPrivilege> selectPrivilegeByRole(String roleId, Integer type){
	  return privilegeMapper.selectPrivilegeByRole(roleId, type);
  }

  @Override
  public TreeSet<LinkappPrivilege> selectPrivilegeByUser(String userId, Integer type){
      if(type == null){type = 0;}
	  return privilegeMapper.selectPrivilegeByUser(userId, type);
  }

    @Override
    public TreeSet<LinkappPrivilege> selectPrivilegeCustomByUser(String tenantId, String userId, Integer type){
        if(type == null){type = 0;}
        return privilegeMapper.selectPrivilegeCustomByUser(tenantId,userId, type);
    }

  @Override
  public void privilege2Role(LinkappRole role, List<LinkappPrivilege> privileges, Integer type) {
	String tenatnId = linkappUserContextProducer.getCurrent().getTenantId();
	privilegeMapper.deletePrivilege2Role(role.getId(), type);
	for(LinkappPrivilege privilege :privileges) {
		LinkappRoleRefPrivilege roleRefPrivilege = new LinkappRoleRefPrivilege();
		roleRefPrivilege.setPrivilegeId(privilege.getId().toString());
		roleRefPrivilege.setTenantId(tenatnId);
		roleRefPrivilege.setRoleId(role.getId().toString());
		roleRefPrivilege.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		privilegeMapper.insertPrivilege2Role(roleRefPrivilege);
	}
  }

    @Override
    public void addPrivilege(LinkappPrivilege linkappPrivilege) {
      if(!StringUtils.isEmpty(linkappPrivilege.getUrl()) && !linkappPrivilege.getUrl().contains("manage" + CommonConstant.DIAGONAL_BAR_STR)){
            throw new IllegalArgumentException("url路径参数不符合规范");
      }
        String tenantId = linkappUserContextProducer.getCurrent().getTenantId();
        if(!StringUtils.isEmpty(linkappPrivilege.getUrl()) && checkPrivilegeUrlRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单路径重复");
        }
        if(checkPrivilegeSeqRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单排序号重复");
        }
        if(checkPrivilegeCodeRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单标识码重复");
        }

        Long id_ = null;
        List<LinkappPrivilege> privilegeMaxId = privilegeMapper.getPrivilegeMaxId();
        if(privilegeMaxId == null || privilegeMaxId.size() <= 0){
          id_ = 1L;
        }else {
            LinkappPrivilege linkappPrivilege1 = privilegeMaxId.get(0);
            Long id = linkappPrivilege1.getId();
            id_ = id + 1;
        }
        linkappPrivilege.setId(id_);
        commonService.setCreateAndModifyInfo(linkappPrivilege);

        linkappPrivilege.setTenantId(tenantId);
        if(linkappPrivilege.getFlag() == null){
            //默认PC端
            linkappPrivilege.setFlag(0);
        }
        if(StringUtils.isEmpty(linkappPrivilege.getCode())){
            Assert.notNull(linkappPrivilege.getUrl(), "url 不能为空");
            String subUrl = linkappPrivilege.getUrl().replaceAll("manage/","");
            String code = subUrl.replaceAll(CommonConstant.DIAGONAL_BAR_STR, CommonConstant.COLON_STR);
            linkappPrivilege.setCode(code);
        }
        privilegeMapper.insertPrivilegeExt(linkappPrivilege);

        TenantRefPrivilege tenantRefPrivilege = new TenantRefPrivilege();
        tenantRefPrivilege.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        tenantRefPrivilege.setTenantId(tenantId);
        tenantRefPrivilege.setPrivilegeId(linkappPrivilege.getId()+"");
        linkappTenantMapper.insertTenant2Privileges(tenantRefPrivilege);
    }

    @Override
    public void updatePrivilege(LinkappPrivilege linkappPrivilege) {
        if(!StringUtils.isEmpty(linkappPrivilege.getUrl()) && checkPrivilegeUrlRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单路径重复");
        }
        if(checkPrivilegeSeqRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单排序号重复");
        }
        if(checkPrivilegeCodeRepeat(linkappPrivilege)){
            throw new IllegalArgumentException("权限菜单标识码重复");
        }
//        String tenantId = linkappUserContextProducer.getCurrent().getTenantId();

        commonService.setModifyInfo(linkappPrivilege);

//        linkappPrivilege.setTenantId(tenantId);
        if(linkappPrivilege.getFlag() == null){
            //默认PC端
            linkappPrivilege.setFlag(0);
        }
        if(StringUtils.isEmpty(linkappPrivilege.getCode())){
            Assert.notNull(linkappPrivilege.getUrl(), "url 不能为空");
            String subUrl = linkappPrivilege.getUrl().replaceAll("manage/","");
            String code = subUrl.replaceAll(CommonConstant.DIAGONAL_BAR_STR, CommonConstant.COLON_STR);
            linkappPrivilege.setCode(code);
        }
        privilegeMapper.updatePrivilegeExt(linkappPrivilege);
    }

    /**
     * 验证权限码是否重复
     * @param linkappPrivilege
     * @return  false未重复， true已存在重复
     */
    private boolean checkPrivilegeUrlRepeat(LinkappPrivilege linkappPrivilege){
        boolean flag = false;
        List<LinkappPrivilege> linkappPrivileges = privilegeMapper.checkPrivilegeUrlIsRepeat(linkappPrivilege);
        if(linkappPrivileges != null && linkappPrivileges.size() > 0){
            flag = true;
        }
        return flag;
    }

    private boolean checkPrivilegeSeqRepeat(LinkappPrivilege linkappPrivilege){
        boolean flag = false;
        Integer resultCount = privilegeMapper.checkPrivilegeSeqIsRepeat(linkappPrivilege);
        if(resultCount != null && resultCount > 0){
            flag = true;
        }
        return flag;
    }

    /***
     * 效验code是否存在相同
     * @param linkappPrivilege
     * @return
     */
    private boolean checkPrivilegeCodeRepeat(LinkappPrivilege linkappPrivilege){
        Assert.notNull(linkappPrivilege.getCode(),"code 不能为空");
        boolean flag = false;
        QueryWrapper<LinkappPrivilege> linkappPrivilegeQueryWrapper = new QueryWrapper<>();
        linkappPrivilegeQueryWrapper.eq(!StringUtils.isEmpty(linkappPrivilege.getCode()),"privilege_code_", linkappPrivilege.getCode())
                .ne(!StringUtils.isEmpty(linkappPrivilege.getId()),"id_", linkappPrivilege.getId());
        Integer resultCount = privilegeMapper.selectCount(linkappPrivilegeQueryWrapper);
        if(resultCount != null && resultCount > 0){
            flag = true;
        }
        return flag;
    }

}
